#include <stdio.h>
#include <sys/time.h>
#include <sched.h>
#include <stdlib.h>
#include <signal.h>
#include <fcntl.h>
#include <error.h>
#include <stdint.h>
#include <pthread.h>
#include <unistd.h>          // 系统调用相关的函数 close()
#include <string.h>          // strcpy, memset(), and memcpy()
#include <sys/types.h>       // 包含了一些基本的系统数据类型 uint8_t、uint16_t 和 uint32_t
#include <sys/socket.h>      // 与套接字相关的函数和数据结构
#include <netinet/in.h>      // 与 Internet 协议族相关的数据结构
#include <netinet/ip.h>      // IP 协议头部的数据结构
#include <netinet/ip_icmp.h> // 定义了 ICMP 协议头部的数据结构
#include <arpa/inet.h>       // 定义了一些 IP 地址转换函数
#include <sys/ioctl.h>       // 进行输入/输出控制的函数和相关宏
#include <bits/ioctls.h>     // 用于 ioctl() 函数的参数
#include <net/if.h>          // 处理网络接口相关的函数和数据结构
#include <linux/if_ether.h>  // 帧格式 以太网帧的一些常量
#include <linux/if_packet.h> // 用于与套接字相关联的网络接口的数据结构 struct sockaddr_ll
#include <net/ethernet.h>    // 以太网帧的数据结构
#include <errno.h>           // errno, perror()
#include <iostream>

#include "../tsmp/tsmp.h"
#include "ptp.h"

const uint32_t MAX_PKT_LEN = 2048;
Sync_state sync_state;
uint8_t buffer[MAX_PKT_LEN];

Ptp_Sync ptp_sync;
extern Port_delay port_delay;
extern SyncInfo syncinfo;
extern TSNConfig config;

const char *filename_sync = "report/gPTPstate_sync.txt";

void printBinary(uint32_t value)
{
    for (int i = 31; i >= 0; i--)
    {
        std::cout << ((value >> i) & 1);
        if (i % 4 == 0)
        {
            std::cout << " "; // Ã¿4Î»ÌíŒÓÒ»žö¿Õžñ
        }
    }
    std::cout << std::endl;
}

uint8_t *sendSync(uint16_t sequence_id)
{
    PtpHeader sync_header;
    init(&sync_header, E_SYNC, sequence_id); // 初始化PTP头
    // printf("init is ok\n");
    // sync_header.message_type = 0x2;
    ptp_sync.sequence_id = sequence_id;
    PtpSync sync;
    memcpy(&sync.ptp_header, &sync_header, sizeof(sync_header));
    memset(sync.padding, 0, 10);
    memcpy(buffer, &sync, sizeof(sync));
    // printf("buff is ok\n");
    return buffer;
}

uint8_t *sendFollowUp()
{
    PtpHeader follow_up_header;
    init(&follow_up_header, E_FOLLOW_UP, ptp_sync.sequence_id); // 初始化PTP头
    PtpFollowUp follow_up;
    memcpy(&follow_up.ptp_header, &follow_up_header, sizeof(follow_up_header));
    uint8_t t1[10] = {0};
    e2t(ptp_sync.t1, t1);                                         // 将八字节的ptp_sync.t1转化成十字节的t1.
    memcpy(&follow_up.precise_origin_timestamp, &t1, sizeof(t1)); // 源时间戳：指的是与之相关联的Sync报文从GM PTP实例中发出时的源时间。
    follow_up.tlv_type = 0x3;                                     // 标识tlv定义的标准组织，本软件该值时0x3
    follow_up.length_field = 0x1c;                                // 该字段标识tlv的长度 0x1C
    uint8_t orgainzation_id[3] = {0x00, 0x80, 0xc2};
    memcpy(&follow_up.orgainzation_id, &orgainzation_id, sizeof(orgainzation_id));
    uint8_t organization_sub_type[3] = {0x00, 0x00, 0x01}; // 该字段是3字节的组织子类型 0x1
    memcpy(&follow_up.organization_sub_type, &organization_sub_type, sizeof(organization_sub_type));
    follow_up.cumulative_scaled_rate_offset = 0x1234;                                                            // 该字段是累积的频率偏移率，计算方法是 (rateRatio -1.0) <<41, 其中rateRatio是GM和该消息发送实体时钟的频率比
    follow_up.gm_time_base_indicator = 0x7d;                                                                     // 设定为125
    uint8_t last_gm_phase_change[12] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; // 最近一次GM时钟相位校正值，初始化时为0. 该字段是有符号的96位的以2^-16纳秒位单位的时间值。
    memcpy(&follow_up.last_gm_phase_change, &last_gm_phase_change, sizeof(last_gm_phase_change));
    follow_up.scaled_last_gm_freq_change = 0x00; // 最近一次GM频率校正值，初始化为0.该字段是32位有符号整型数值。
    memcpy(buffer, &follow_up, sizeof(follow_up));
    // printf("------------主节点没上报\n");
    syncinfo.CorrectionField = follow_up_header.correction_field;
    syncinfo.GMRateRatio = 1;
    syncinfo.NeighborRateRatio = port_delay.neighbour_rateratio;
    syncinfo.CumulativeScaledRateOffset = 0;
    syncinfo.tickLength = 1;
    syncinfo.offset = 0;
    syncinfo.SequenceID = ptp_sync.sequence_id;
    syncinfo.PreciseOriginTimestamp = ptp_sync.t1;
    syncinfo.RecvTimestamp = 0;

    write_to_syncfile(syncinfo, filename_sync);
    // printf("------------主节点已上报\n");
    return buffer;
}

// 接收sync帧
int parseSync(Pack_rec tsmp_pack) // 需要tsmp
{
    PtpSync sync;
    memcpy(&sync, &tsmp_pack.payload, sizeof(sync));
    ptp_sync.sequence_id = ntohs(sync.ptp_header.sequence_id);
    sync_state = Sync_state::RECV_SYNC;
    return 0;
}

uint64_t t1;
int parseFollowUp(Pack_rec tsmp_pack)
{
    uint32_t data[1];
    int32_t offset;
    if (sync_state != Sync_state::RECV_SYNC)
    {
        std::cout << "recv sync pkt error, state_ = " << (int)sync_state;
        return -1;
    }
    PtpFollowUp followup;
    memcpy(&followup, &tsmp_pack.payload, sizeof(tsmp_pack.payload));
    followup.ptp_header.sequence_id = ntohs(followup.ptp_header.sequence_id);
    if (followup.ptp_header.sequence_id != ptp_sync.sequence_id)
    {
        printf("sequence id error, follow up sequence id is %x, ptp_sync sequence id is %x\n", followup.ptp_header.sequence_id, ptp_sync.sequence_id);
        printf("The value of the last offset：%d\n", ptp_sync.offset);
        data[0] = ptp_sync.offset;
    }
    else
    {
        t1 = t2e(followup.precise_origin_timestamp);
        ptp_sync.t1 = t1;
        // printf("t1:%lx\n", t1);
        // printf("parse follow up successfully\n");
        sync_state = Sync_state::RECV_FOLLOW_UP;
        offset = calculateOffset();
        if (sync_state == Sync_state::SYNC_DONE)
        {
            data[0] = int32toReg(offset);
            // printf("data[0] = %u\n", data[0]);
            // printf("data[0] = %x\n", data[0]);
            printBinary(data[0]);
            data[0] = htonl(data[0]);
            ptp_sync.offset = data[0];
            // readReqSend(0x00080004,2);
            writeReqSend(0x00080000, 1, data);
            // readReqSend(0x00080004,2);
            printf("offset writeReqSend send successfully\n");
            syncinfo.CorrectionField = followup.ptp_header.correction_field;
            syncinfo.GMRateRatio = port_delay.neighbour_rateratio;
            syncinfo.NeighborRateRatio = port_delay.neighbour_rateratio;
            syncinfo.CumulativeScaledRateOffset = 0;
            syncinfo.tickLength = 1;
            syncinfo.offset = offset;
        }
        syncinfo.SequenceID = ptp_sync.sequence_id;
        syncinfo.PreciseOriginTimestamp = t1;
        syncinfo.RecvTimestamp = ptp_sync.t0;
    }
    write_to_syncfile(syncinfo, filename_sync);

    return 0;
}

// 计算offset
int32_t calculateOffset()
{

    if (port_delay.neighbour_rateratio == 0)
    {
        printf("I need neighbour rateratio to calculate offset\n");
        return 0;
    }
    // 提取秒和纳秒部分
    int32_t gm_time;
    int32_t offset;
    int32_t t0_time;
    uint32_t gm_seconds = extract_seconds(ptp_sync.t1);
    uint32_t gm_nanoseconds = extract_nanoseconds(ptp_sync.t1);
    uint32_t t0_seconds = extract_seconds(ptp_sync.t0);
    uint32_t t0_nanoseconds = extract_nanoseconds(ptp_sync.t0);
    if (gm_seconds == t0_seconds)
    {
        gm_time = int(gm_nanoseconds);
        t0_time = int(t0_nanoseconds);
    }
    else
    {
        printf("11111111111111111gm_seconds:%x\n", gm_seconds);
        printf("11111111111111111t0_seconds:%x\n", t0_seconds);
        if (gm_seconds > t0_seconds)
        {
            offset = 125 * 1e6;
        }
        else
        {
            offset = -125 * 1e6;
        }
        sync_state = Sync_state::SYNC_DONE;
        return offset;
    }
    printf("22222222222222222222222222\n");
    // 计算
    if (gm_time - t0_time > 125 * 1e6)
    {
        offset = 125 * 1e6;
    }
    else if (t0_time - gm_time > 125 * 1e6)
    {
        offset = -125 * 1e6;
    }
    else
    {
        offset = gm_time + port_delay.link_delay - t0_time;
    }
    printf("gm_time = %u\n", gm_time);
    printf("t0_time = %u\n", t0_time);
    printf("offset = %d \n", offset);
    sync_state = Sync_state::SYNC_DONE;
    return offset;
}

// 计算ticklen
uint32_t calculateticklen()
{

    if (port_delay.neighbour_rateratio == 0)
    {
        printf("I need neighbour rateratio to calculate ticklen\n");
        return 0;
    }

    // 提取秒和纳秒部分
    uint32_t gm_seconds = extract_seconds(ptp_sync.t1);
    uint32_t gm_nanoseconds = extract_nanoseconds(ptp_sync.t1);
    int64_t gm_time = 1e9 * gm_seconds + gm_nanoseconds;
    uint32_t t0_seconds = extract_seconds(ptp_sync.t0);
    uint32_t t0_nanoseconds = extract_nanoseconds(ptp_sync.t0);
    int64_t t0_time = 1e9 * t0_seconds + t0_nanoseconds;

    // 计算
    int32_t offset = gm_time + port_delay.link_delay * port_delay.neighbour_rateratio - t0_time * port_delay.neighbour_rateratio;
    printf("offset = %d \n", offset);
    return offset;
}

uint32_t int32toReg(int32_t value)
{
    int32_t temp;
    if (value >= 0)
        temp = value;
    else
        temp = -value;

    uint32_t result;
    if (value >= 0)
    {
        // 数据为正值，第28位为0
        result = (uint32_t)temp;
        result &= ~(1U << 27); // 清除第28位
    }
    else
    {
        // 数据为-值，第28位为1
        result = (uint32_t)temp;
        result |= (1U << 27); // 设置第28位为1
    }

    return result;
}
